/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package gui.animation;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.Point2D;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

import physics.Circle;
import physics.Rectangle;
import physics.Shape;
import physics.Vector;
import physics.World;

public final class SceneFrame extends JFrame {
	private boolean fixed = false;
	private double mass = 1.0;
	private double width = 40;
	private double gravity = 1.0;

    private Animator animator;
    private Painter painter;
    private World scene;

    private JLabel canvas;
    
    public SceneFrame(World scene, int width, int height) {
        super("Ian McBride's Physics Demo");
        this.setBounds(0, 0, width, height);
        this.scene = scene;
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
        init();
    }

    private void init() {
        Viewport viewport = new Viewport(640, 480);
        animator = new Animator(scene);
        painter = new Painter(scene, viewport, this);
        canvas = new JLabel(new ImageIcon(viewport.getImage()));
        canvas.addMouseListener(new MouseHandler());
        add(canvas);
        pack();
        animator.start();
        painter.start();
    }

    /*
     * Entry point
     */
    public static void main(String[] args) {
    	World scene = new World();
    	scene.addShapes(makeBorders());
        new SceneFrame(scene, 640, 480);
        
    }
    
    private static ArrayList<Shape> makeBorders() {

    	Rectangle top = new Rectangle(new Vector(-630,241), new Vector(630,1000), true);
		Rectangle bot = new Rectangle(new Vector(-630,-2000), new Vector(630,-241), true);
		Rectangle left = new Rectangle(new Vector(-1000,-240), new Vector(-320,240), true);
		Rectangle right = new Rectangle(new Vector(320, -240), new Vector(2000,240), true);
		
		ArrayList<Shape> borders = new ArrayList<Shape>();
		borders.add(top);
		borders.add(bot);
		borders.add(left);
		borders.add(right);
		
		return borders;
	}

    /*
     * Listeners
     */

    private class MouseHandler implements MouseListener {
    	private Point2D.Double mouseDown;
        
        public void mouseClicked(MouseEvent e) {
            
        }

        public void mousePressed(MouseEvent e) {
        	mouseDown = painter.getViewport().getPoint(e.getPoint());
        }

        public void mouseReleased(MouseEvent e) {
        	Point2D.Double mouseUp = painter.getViewport().getPoint(e.getPoint());
        	Vector vel = new Vector((mouseUp.x - mouseDown.x)/3,
        			                (mouseUp.y - mouseDown.y)/3);
        	Shape b;
        	if(e.getButton() == MouseEvent.BUTTON1) {
        		b = new Circle(new Vector(mouseDown.x, mouseDown.y), vel, 
        				width * .6, mass, gravity, fixed);
        	} else /*if(e.getButton() == MouseEvent.BUTTON2)*/ {
        		b = new Rectangle(new Vector(mouseDown.x, mouseDown.y), 
        				width, width, vel, gravity, mass, fixed);
        	}
        	synchronized(scene) {
        		scene.addShape(b);
        	}
        }

        public void mouseEntered(MouseEvent e) {
            
        }

        public void mouseExited(MouseEvent e) {
            
        }
        
    }
    
    private class KeyHandler implements KeyListener {

        private static final double SPEED = 5;

        public void keyTyped(KeyEvent e) {

        }

        public void keyPressed(KeyEvent e) {
            Viewport v = painter.getViewport();
            switch (e.getKeyCode()) {
                case KeyEvent.VK_F:
                    fixed = !fixed;
                    break;
                case KeyEvent.VK_S:
                    mass -= .2;
                    break;
                case KeyEvent.VK_D:
                    mass += .2;
                    break;
                case KeyEvent.VK_A:
                    gravity -= .2;
                    break;
                case KeyEvent.VK_Z:
                    gravity += .2;
                    break;
                case KeyEvent.VK_X:
                	if(width > 5)
                		width -= 5;
                    break;
                case KeyEvent.VK_C:
                    width += 5;
                    break;
                case KeyEvent.VK_ESCAPE:
                    scene.setWorld(new ArrayList<Shape>());
                    break;
            }
        }

        public void keyReleased(KeyEvent e) {
            
        }

    }
}
